﻿using OneCard.Face8280Module.DeviceModel.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using OneCard.Face8280Module.Utility;
using System.Security.Cryptography;

namespace OneCard.Face8280Module.Controllers
{
    public class ReplayAttackFillter : IActionFilter
    {
        IMemoryCache _Cache;
        private static object _Lock = new object();
        private static JsonResult ErrorResult = new JsonResult(
            new FaceAPIResult() { msg = "Replay Attack", success = 0 });

        public ReplayAttackFillter(IMemoryCache cache)
        {
            _Cache = cache;
        }

        /// <summary>
        /// 检查重放攻击
        /// </summary>
        /// <param name="RequestMD5">请求的MD5</param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private bool CheckReplayAttack(string RequestMD5)
        {
            if (RequestMD5 == null) return true;
            string value = _Cache.Get<string>(RequestMD5);
            if (value != null) return true;
            lock (_Lock)
            {
                value = _Cache.Get<string>(RequestMD5);
                if (value != null) return true;
                _Cache.Set(RequestMD5, "ok", TimeSpan.FromSeconds(120));
            }

            return false;
        }


        public void OnActionExecuting(ActionExecutingContext context)
        {
            var Request = context.HttpContext.Request;
            StringBuilder sBuf = new StringBuilder(4000);
            sBuf.Append(Request.Host.ToString());
            sBuf.Append(Request.Path.ToString());
            //foreach (var item in Request.Headers)
            //{
            //    sBuf.Append(item.Key);
            //    sBuf.Append(String.Join(',', item.Value.ToArray()));
            //}
            foreach (var item in Request.Query)
            {
                sBuf.Append(item.Key);
                sBuf.Append(string.Join(',', item.Value.ToArray()));
            }
            foreach (var item in context.ActionArguments)
            {
                sBuf.Append(item.Key);
                sBuf.Append(item.Value.ToString());
            }

            string sKey = string.Empty;

            sKey = MD5Helper.GetStringMD5(sBuf.ToString());

            if (string.IsNullOrEmpty(sKey)) return;
            if (CheckReplayAttack(sKey))
            {
                Console.WriteLine($"请求被拦截：{Request.Path.ToString()}");
                context.Result = ErrorResult;
            }


        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            //
        }
    }
}
